#ifndef __MY_HOST_
#define __MY_HOST_

#include "mq_exchange.hpp"
#include "mq_queue.hpp"
#include "mq_binding.hpp"
#include "mq_message.hpp"


namespace chenmq
{
    //将四个模块整合到一起，对外提供对应的接口
    class VirtualHost
    {
    public:
        using ptr = std::shared_ptr<VirtualHost>;
        VirtualHost(const std::string& hname, const std::string& basedir, const std::string& dbfile)
            :_host_name(hname)
            ,_emp(std::make_shared<ExchangeManager>(dbfile))
            ,_mqmp(std::make_shared<MsgQueueManager>(dbfile))
            ,_bmp(std::make_shared<BindingManager>(dbfile))
            ,_mmp(std::make_shared<MessageManager>(basedir))
        {
            //其余的都是在构造函数里面恢复历史数据的，但是消息的历史是数据是在声明队列的时候进行恢复的
            QueueMap qm = _mqmp->allQueues();
            for(auto& q: qm)
            {
                _mmp->initQueueMessage(q.first);
            }
        }

        //声明/删除一个交换机
        void declareExchange(const std::string& name, ExchangeType type, 
            bool durable, bool auto_delete, std::unordered_map<std::string, std::string>& args)
            {
                return _emp->declareExchange(name, type, durable, auto_delete, args); 
            }
        void deleteExchange(const std::string& name)
        {
            //在删除交换机之前，需要删除交换机相关的绑定信息
            _bmp->removeExchangeBindings(name);
            return _emp->deleteExchange(name);
        }
        bool existsExchange(const std::string& name)
        {
            return _emp->exists(name);
        }
        Exchange::ptr selectExchange(const std::string& ename)
        {
            return _emp->selectExchange(ename);
        }

        //声明/删除一个队列
        bool declareQueue(const std::string &qname,
                          bool qdurable,
                          bool qexclusive,
                          bool qauto_delete,
                          const std::unordered_map<std::string, std::string> &qargs)
        {
            //先初始化队列的消息句柄，然后创建队列
            _mmp->initQueueMessage(qname);
            return _mqmp->declareQueue(qname, qdurable, qexclusive, qauto_delete, qargs);
        }

        bool deleteQueue(const std::string& name)
        {
            //删除队列，1 删除队列的消息 2 队列的绑定信息
            _mmp->destroyQueueMessage(name);
            _bmp->removeMsgQueueBindings(name);
            return _mqmp->exists(name);
        }

        bool existsQueue(const std::string& name)
        {
            return _mqmp->exists(name);
        }

        QueueMap allQueues()
        {
            return _mqmp->allQueues();
        }


        //添加/解除绑定
        bool Bind(const std::string &ename, const std::string &qname, const std::string &key)
        {
            Exchange::ptr ep = _emp->selectExchange(ename);
            if(ep.get() == nullptr)
            {
                DLOG("添加绑定失败，交换机%s不存在 ", ename.c_str());
                return false;
            }

            MsgQueue::ptr mqp = _mqmp->selectQueue(qname);
            if(mqp.get() == nullptr)
            {
                DLOG("进行队列绑定失败, 队列 %s不存在", qname.c_str());
                return false;
            }

            //如果交换机和队列都是持久化的，那么这个绑定信息也是持久化的
            return _bmp->bind(ename, qname, key, ep->durable && mqp->durable);
        }
        void unBind(const std::string& ename, const std::string& qname)
        {
            _bmp->unBind(ename, qname);
        }

        //获得一个交换机上的所有绑定信息 (MsgQueueBindingMap， 队列名称和绑定信息的映射关系)
        MsgQueueBindingMap exchangeBindings(const std::string& ename)
        {
            return _bmp->getExchangeBindings(ename);
        }

        bool existsBinding(const std::string& ename, const std::string& qname)
        {
            return _bmp->exists(ename, qname);
        }

        //发布/消息/确认一条消息
        bool basicPublish(const std::string& qname, BasicProperties* bp, 
                    const std::string& body)
            {
                MsgQueue::ptr mqp = _mqmp->selectQueue(qname);   
                if(mqp.get() == nullptr)
                {
                    DLOG("发布消息失败,队列%s不存在", qname.c_str());
                    return false;
                }
                return _mmp->insert(qname, bp, body, mqp->durable);
            }

        //消费一条消息，但是还没有确认
        MessagePtr basicConsume(const std::string& qname)
        {
            return _mmp->front(qname);
        }
        
        void basicAck(const std::string& qname, const std::string& msgid)
        {
            return _mmp->ack(qname, msgid);
        }

        void clear()
        {
            _emp->clear();
            _mqmp->clear();
            _bmp->clear();
            _mmp->clear();
        }
    private:
        std::string _host_name;
        ExchangeManager::ptr _emp;  //交换机管理句柄
        MsgQueueManager::ptr _mqmp; //队列的管理句柄
        BindingManager::ptr _bmp;   //绑定的管理句柄
        MessageManager::ptr _mmp;   //消息的管理句柄
    };
}


#endif